﻿package com.usfuture.chart.techanly.line{


	import com.usfuture.chart.IChart;
	import com.usfuture.chart.techanly.AbstractTechProperty;
	import com.usfuture.chart.techanly.ITechAnlyChart;
	import com.usfuture.chart.util.GraphicsUtil;
	import com.usfuture.event.DataEvent;
	import com.usfuture.techanly.entity.Line;
	import com.usfuture.techanly.entity.Ma;
	import com.usfuture.techanly.entity.MaParams;
	import com.usfuture.util.DateTimeUtils;
	import com.usfuture.util.NumberFormat;
	
	import fl.controls.Label;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;

	public class LineChart extends EventDispatcher implements ITechAnlyChart {
		
		private var _data:Array;
		private var _canvas:Sprite;
		private var _madata:Array=new Array;
		private var _maParamsArr:Array;
		private var _canvasWidth:Number;
		private var _canvasHeigth:Number;
		private var _highPrice:Number;
		private var _lowPrice:Number;
		private var _cursor:Sprite=new Sprite;
		private var _leftWidthX:Number;//K线图距画布左边的距离
		private var _topHeightY:Number=16;//K线图距画布上边的距离
		private var _bottomHeightY:Number=5;//K线图距画布下边的距离
		private var _width:Number;//K线宽
		private var _height:Number;//K线高
		private var _startPoint:Point;//K线开始位置
		private var highPriceLabel:TextField = new TextField();
		private var lowPriceLabel:TextField = new TextField();
		private var lineTypeLabel:TextField = new TextField();
		private var leftLabels:Array = new Array;//左边的价格label数组
		private var ydivideNum:int = 8;//y轴等分数
		private var _techProperty:AbstractTechProperty;
		private var _lineShow:TextField;

		public function LineChart(canvas:Sprite,maParamsArr:Array) {
			this._canvas = canvas;
			this._maParamsArr = maParamsArr;
			this._canvas.addChild(_cursor);
			this.addEventListener(MouseEvent.MOUSE_MOVE,onMovseMove);
			_lineShow = new TextField;
			_lineShow.border = true;
			_lineShow.borderColor = 0x969696;
			_lineShow.multiline = true;
			_lineShow.background = true;
			_lineShow.backgroundColor = 0xffffff;
			_lineShow.width = 100;
			_lineShow.height = 110;
			_lineShow.visible = false;
			this._canvas.addChild(_lineShow);
			loadLeftLabel();
			measure();
		}
		
		
		/**
		 * 加载左边label
		 */
		private function loadLeftLabel():void{
			var textFormat:TextFormat = new TextFormat;
			textFormat.align = TextFormatAlign.RIGHT;
			textFormat.bold = true;
			textFormat.color = 0x716857;
			textFormat.font = "Arial";
			textFormat.size = 10;
			
			for(var i=0;i<ydivideNum;i++){
				var leftLabel:TextField = new TextField();
				leftLabel.defaultTextFormat = textFormat;
				leftLabel.selectable = false;
				leftLabels.push(leftLabel);
				this._canvas.addChild(leftLabel);
			}
		}
		
		public function measure():void{
			this._canvasWidth = _canvas.width;
			this._canvasHeigth = _canvas.height-1;
			this._leftWidthX = AbstractTechProperty.leftWidthX;
			this._width=_canvasWidth-_leftWidthX;
			this._height=_canvasHeigth-_topHeightY-_bottomHeightY;
			this._startPoint = new Point(_leftWidthX,_topHeightY);
			
			for(var i=0;i<ydivideNum;i++){
				var leftLabel:TextField = leftLabels[i] as TextField;
				leftLabel.x=0;
				leftLabel.y=_startPoint.y+_height*(i/ydivideNum)-10;
				leftLabel.width=_leftWidthX;
			}
			
			highPriceLabel.y=_startPoint.y;
			lowPriceLabel.y=_startPoint.y+_height-10;
			
			
			lineTypeLabel.x=0;
			lineTypeLabel.y=-5;
			lineTypeLabel.width=_leftWidthX;
			
			repaint();
		}

		
		public function paint():void{
			
			//画背景
			drawBackground();
			if(!_data||_data.length==0)
				return;
			
			//计算峰值
			calPeakValue();
			//画左边的数字
			drawLeftNum();
			//画图
			drawLine();
			//画均线
			drawMa();
		}
		
		
		public function drawBackground():void{
			//画矩形
			this._canvas.graphics.lineStyle(1,0x626957,1);
			this._canvas.graphics.beginFill(0xffffff,0);
			this._canvas.graphics.drawRect(_leftWidthX,0,_width,_canvasHeigth);
			
			//画虚线
			for(var i=0;i<ydivideNum;i++){
				var beginPoint:Point=new Point(_startPoint.x,_startPoint.y + i/ydivideNum*_height);
				var endPoint:Point=new Point(_startPoint.x+_width,_startPoint.y + i/ydivideNum*_height);
				GraphicsUtil.drawDashed(this._canvas.graphics,beginPoint,endPoint,5,2);
			}

		}
		
		public function drawLeftNum():void{
			for(var i=0;i<ydivideNum;i++){
				var leftLabel:TextField = leftLabels[i] as TextField;
				leftLabel.text = NumberFormat.dynamicPrecisionStr(_highPrice-(_highPrice-_lowPrice)*(i/ydivideNum))
			}
//			lineTypeLabel.text = line.lineType;
		}
		
		
		public function drawLine():void{
			var lastlyDate:int = -1;
			if(techProperty.mode){
				for(var i:int=(techProperty.startPos-techProperty.lineNum<0?0:techProperty.startPos-techProperty.lineNum),j:int=0;i<techProperty.startPos;i++,j++){
					if(i<0) break;
					var dailyLine:Line=Line(_data[i]);
					
					if(AbstractTechProperty.lineTypeShow(AbstractTechProperty.lineType).indexOf("分鐘")!=-1&&lastlyDate!=-1 && lastlyDate!=dailyLine.timestamp.date){
						this._canvas.graphics.lineStyle(1,0x626957,0.5);
						var beginPoint:Point=new Point(_startPoint.x+j*(techProperty.lineWidth+techProperty.lineMergin),0);
						var endPoint:Point=new Point(_startPoint.x+j*(techProperty.lineWidth+techProperty.lineMergin),_startPoint.y + _height+_bottomHeightY);
						GraphicsUtil.drawDashed(this._canvas.graphics,beginPoint,endPoint,10,2);
					}
					lastlyDate=dailyLine.timestamp.date;
					//设置颜色
					if(dailyLine.closePrice>dailyLine.openPrice){
						this._canvas.graphics.lineStyle(1,0xD30006,1);
						this._canvas.graphics.beginFill(0xD30006,1);
					}else if(dailyLine.closePrice==dailyLine.openPrice){
						this._canvas.graphics.lineStyle(1,0x817B6D,1);
						this._canvas.graphics.beginFill(0x817B6D,1);
					}else{
						this._canvas.graphics.lineStyle(1,0x009303,1);
						this._canvas.graphics.beginFill(0x009303,1);
					}
					
	
					//画直线	
					var hightLinePos:Number = calYAxis(dailyLine.highPrice);
					var lowLinePos:Number = calYAxis(dailyLine.lowPrice);
					this._canvas.graphics.moveTo(_startPoint.x+(j+1)*(techProperty.lineWidth+techProperty.lineMergin)-(techProperty.lineWidth/2+techProperty.lineMergin),hightLinePos);
					this._canvas.graphics.lineTo(_startPoint.x+(j+1)*(techProperty.lineWidth+techProperty.lineMergin)-(techProperty.lineWidth/2+techProperty.lineMergin),lowLinePos);	
					
					//画矩形
					var openRectPos:Number = calYAxis(dailyLine.openPrice);
					var closeRectPos:Number = calYAxis(dailyLine.closePrice);
					if(openRectPos==closeRectPos)
						closeRectPos+=1;
					this._canvas.graphics.drawRect(_startPoint.x+j*(techProperty.lineWidth+techProperty.lineMergin),closeRectPos,techProperty.lineWidth,(openRectPos-closeRectPos));
					this._canvas.graphics.endFill();

				}
			}else{
				for(var i:int=(techProperty.startPos-techProperty.lineNum<0?0:techProperty.startPos-techProperty.lineNum),j:int=0;i<techProperty.startPos;i++,j++){
					if(i<0) break;
					var dailyLine:Line=_data[i] as Line;
					if(AbstractTechProperty.lineTypeShow(AbstractTechProperty.lineType).indexOf("分鐘")!=-1&&lastlyDate!=-1 && lastlyDate!=dailyLine.timestamp.date){
						this._canvas.graphics.lineStyle(1,0x626957,0.5);
						var beginPoint:Point=new Point(_startPoint.x+j*(techProperty.lineWidth+techProperty.lineMergin),0);
						var endPoint:Point=new Point(_startPoint.x+j*(techProperty.lineWidth+techProperty.lineMergin),_startPoint.y + _height+_bottomHeightY);
						GraphicsUtil.drawDashed(this._canvas.graphics,beginPoint,endPoint,10,2);
					}
					lastlyDate=dailyLine.timestamp.date;
					//设置颜色
					if(dailyLine.closePrice>dailyLine.openPrice){
						this._canvas.graphics.lineStyle(1,0xD30006,1);
						this._canvas.graphics.beginFill(0xD30006,1);
					}else if(dailyLine.closePrice==dailyLine.openPrice){
						this._canvas.graphics.lineStyle(1,0x817B6D,1);
						this._canvas.graphics.beginFill(0x817B6D,1);
					}else{
						this._canvas.graphics.lineStyle(1,0x009303,1);
						this._canvas.graphics.beginFill(0x009303,1);
					}
					
					//画直线	
					hightLinePos = calYAxis(dailyLine.highPrice);
					lowLinePos = calYAxis(dailyLine.lowPrice);
					this._canvas.graphics.moveTo(_startPoint.x+(j+1)*(_width/techProperty.lineNum),hightLinePos);
					this._canvas.graphics.lineTo(_startPoint.x+(j+1)*(_width/techProperty.lineNum),lowLinePos);	
					this._canvas.graphics.endFill();
				}
			}
		}
		
		/**
		 * 画均线
		 */
		public function drawMa():void{
			
			for(var i:int=(techProperty.startPos-techProperty.lineNum<0?1:techProperty.startPos-techProperty.lineNum+1),j:int=1;i<techProperty.startPos;i++,j++){
				if(i<0) break;
				var nowMas:Object = _madata[i];
				var preMas:Object=_madata[i-1<0?0:i-1];
				var preX:Number = techProperty.mode?_startPoint.x+(j)*(techProperty.lineWidth+techProperty.lineMergin)-(techProperty.lineWidth/2+techProperty.lineMergin):_startPoint.x+(j)*(_width/techProperty.lineNum);
				var nowX:Number=techProperty.mode?_startPoint.x+(j+1)*(techProperty.lineWidth+techProperty.lineMergin)-(techProperty.lineWidth/2+techProperty.lineMergin):_startPoint.x+(j+1)*(_width/techProperty.lineNum);
				for(var k:int=0;k<_maParamsArr.length;k++){
					var maParams:MaParams=_maParamsArr[k] as MaParams;
					if(preMas[maParams.ma]){
						var prePos:Number=calYAxis(preMas[maParams.ma]);
						var nowPos:Number=calYAxis(nowMas[maParams.ma]);
						var prePoint:Point = new Point(preX,prePos);
						var nowPoint:Point  = new Point(nowX,nowPos);
						if((prePoint.y<_startPoint.y&&nowPoint.y<_startPoint.y)||(prePoint.y>_startPoint.y+_height&&nowPoint.y>_startPoint.y+_height)){continue;}
						else if((prePoint.y<_startPoint.y&&nowPoint.y>_startPoint.y)||(prePoint.y>_startPoint.y&&nowPoint.y<_startPoint.y)){
							prePoint.y = _startPoint.y;
							prePoint.x = (prePoint.x-nowPoint.x)*(_startPoint.y-nowPoint.y)/(prePoint.y-nowPoint.y)+nowPoint.x;
						}
							
						else if((prePoint.y<(_startPoint.y+_height)&&nowPoint.y>(_startPoint.y+_height))||(prePoint.y>(_startPoint.y+_height)&&nowPoint.y<(_startPoint.y+_height))){
							prePoint.y = _startPoint.y+_height;
							prePoint.x = (prePoint.x-nowPoint.x)*(_startPoint.y+_height-nowPoint.y)/(prePoint.y-nowPoint.y)+nowPoint.x;
						}
						
						this._canvas.graphics.lineStyle(1,maParams.color,1)
						this._canvas.graphics.moveTo(prePoint.x,prePoint.y);
						this._canvas.graphics.lineTo(nowPoint.x,nowPoint.y);
						this._canvas.graphics.endFill();
					}
				}		
			}
		}
		
		public function calYAxis(price:Number):Number{
			return _startPoint.y+(_highPrice-price)/(_highPrice-_lowPrice)*_height;
		}
		
		
		
		public function calPeakValue():void{
			var dailyLine:Line = _data[techProperty.startPos-1] as Line;
			_highPrice = dailyLine.highPrice;
			_lowPrice = dailyLine.lowPrice;
			for(var i:int=techProperty.startPos-1;i>=(techProperty.startPos-techProperty.lineNum);i--){
				if(i<0) break;
				dailyLine=Line(_data[i]);
				if(dailyLine.highPrice>_highPrice)
					_highPrice = dailyLine.highPrice;
				if(dailyLine.lowPrice<_lowPrice)
					_lowPrice = dailyLine.lowPrice;
			}
			if(_highPrice==_lowPrice){
				_highPrice = _highPrice*1.1;
				_lowPrice =_lowPrice*0.9;
			}
		}
		
		
		public function repaint():void{
			
			this._canvas.graphics.clear();
			paint();
		}
		
		public function set data(value:Array):void
		{
			_data = value;
			_madata = new Array();
			
			for(var i:int=0;i<_data.length;i++){
				var line:Line = _data[i] as Line;
				var mas:Object = new Object();
				for(var k:int=0;k<_maParamsArr.length;k++){
					var maParams:MaParams = _maParamsArr[k] as MaParams;
					var ma:Ma = new Ma();
					if(i>=maParams.ma-1){
						var price:Number=0;
						for(var j:int=i;j>=i-(maParams.ma-1);j--)
							price+=Line(_data[j]).closePrice;
						ma.ma=price/maParams.ma;
					}
					mas[maParams.ma]=ma.ma;
				}
				_madata.push(mas);
			}
			for(var i:int=0;i<_data.length;i++){
				var line:Line=Line(_data[i]);
				var perLine:Line=Line(_data[i-1<0?0:i-1]);
				//设置昨收价
				if(i==0)
					line.ycPrice=line.openPrice;
				else
					line.ycPrice=perLine.closePrice;
			}
			
		}
		
		public function onMovseMove(event:MouseEvent):void
		{
			
			if(!_data||_data.length==0)
				return;
			var pos:int=0;
			if(techProperty.mode)
				pos=(_canvas.mouseX-_leftWidthX)/(techProperty.lineWidth+techProperty.lineMergin);
			else
				pos=(_canvas.mouseX-_leftWidthX)/((_canvas.width-_leftWidthX)/techProperty.lineNum);
			var index:int = techProperty.startPos-techProperty.lineNum+pos>=_data.length?_data.length-1:techProperty.startPos-techProperty.lineNum+pos
			var line:Line=_data[index<0?0:index];
			var mas:Object=_madata[index<0?0:index];
			
//			_cursor.graphics.clear();
//			_cursor.graphics.lineStyle(1,0x000000);
			var xaxis:Number = 0;
			if(techProperty.mode)
				xaxis = _leftWidthX + pos*(techProperty.lineWidth+techProperty.lineMergin) + techProperty.lineWidth/2;
			else
				xaxis = _leftWidthX + pos*((_canvas.width-_leftWidthX)/techProperty.lineNum);
			var yaxis:Number = calYAxis(line.closePrice);
//
//			//横线
//			yaxis = Math.max(yaxis,0);
//			yaxis = Math.min(yaxis,_canvas.height);
//			_cursor.graphics.moveTo(_leftWidthX,yaxis);
//			_cursor.graphics.lineTo(_canvas.width,yaxis);
//			//竖线
//			xaxis = Math.min(xaxis,_canvas.width);
//			xaxis =  Math.max(_leftWidthX,xaxis);
//			_cursor.graphics.moveTo(xaxis,0);
//			_cursor.graphics.lineTo(xaxis,_canvas.height);
//			//小圆圈
//			_cursor.graphics.beginFill(0xFFFDE8,1);
//			_cursor.graphics.drawCircle(xaxis,yaxis,1);
//			_cursor.graphics.endFill();
			
			//列表位置
			if(xaxis>=_startPoint.x+_width-_lineShow.width-20){
				_lineShow.x=xaxis - _lineShow.width-20;
			}
			else
				_lineShow.x=xaxis+20;
			if(yaxis>=_startPoint.y+_height-_lineShow.height-20){
				_lineShow.y=yaxis - _lineShow.height-20;
			}
			else
				_lineShow.y=yaxis+20;
			
			if(_lineShow.y < 0)
				_lineShow.y = 5;
			
			//当前鼠标所在的K线的X、Y位置
			var kx:Number;
			var kyl:Number;
			var kyh:Number;
			if(techProperty.mode)
				kx = _leftWidthX + pos*(techProperty.lineWidth+techProperty.lineMergin);
			else
				kx = _leftWidthX + pos*((_canvas.width-_leftWidthX)/techProperty.lineNum);
			
			kyl = calYAxis(line.lowPrice);
			kyh = calYAxis(line.highPrice);
			//如果鼠标在K线范围内，则显示面板
			if((this._canvas.mouseX>=kx&&this._canvas.mouseX<=kx+techProperty.lineWidth)&&(this._canvas.mouseY>=kyh-5&&this._canvas.mouseY<=kyl+5))
				_lineShow.visible = true;
			else
				_lineShow.visible = false;
			
			//显示K线值
			var linetxt:String = '';
			if(AbstractTechProperty.lineType==AbstractTechProperty.LINE_DAILY)
				linetxt+='<font color="#4C1650">日    期:</font>'+DateTimeUtils.date2Str(line.timestamp,1).substr(0,10)+'<br>';
			else
				linetxt+='<font color="#4C1650">日    期:</font>'+DateTimeUtils.date2Str(line.timestamp,1).substr(5,11)+'<br>';
			//linetxt+='<font color="#4C1650">time:</font>'+time+'<br>';
			linetxt+='<font color="#4C1650">收盤價:</font><font style="font-family:Arial;" color="'+getColor(line.closePrice,line.ycPrice)+'">'+NumberFormat.dynamicPrecisionStr(line.closePrice)+'</font><br>';
			linetxt+='<font color="#4C1650">漲    跌:</font><font color="'+getColor(line.closePrice,line.ycPrice)+'">'+(line.rise>0?'↑':'↓')+NumberFormat.dynamicPrecisionStr(Math.abs(line.rise))+'</font><br>';
			linetxt+='<font color="#4C1650">成交量:</font>'+int(line.volume)+'<br>';
			linetxt+='<font color="#4C1650">開盤價:</font><font color="'+getColor(line.openPrice,line.ycPrice)+'">'+NumberFormat.dynamicPrecisionStr(line.openPrice)+'</font><br>';
			linetxt+='<font color="#4C1650">最高價:</font><font color="'+getColor(line.highPrice,line.ycPrice)+'">'+NumberFormat.dynamicPrecisionStr(line.highPrice)+'</font><br>';
			linetxt+='<font color="#4C1650">最低價:</font><font color="'+getColor(line.lowPrice,line.ycPrice)+'">'+NumberFormat.dynamicPrecisionStr(line.lowPrice)+'</font><br>';
			_lineShow.htmlText =linetxt;
			
			//派发当前鼠标所在的K线数据事件 
			dispatchEvent(new DataEvent(DataEvent.CURRENT_MOUSE_POSITION_DATA,{'line':line,'mas':mas}));
			
		}

		public function get techProperty():AbstractTechProperty
		{
			return _techProperty;
		}

		public function set techProperty(value:AbstractTechProperty):void
		{
			_techProperty = value;
			_techProperty.removeEventListener(AbstractTechProperty.CHANGE,change);
			_techProperty.addEventListener(AbstractTechProperty.CHANGE,change);
		}
		
		private function change(event:Event):void{
			repaint();
		}
		
		private function getColor(price:Number,close:Number):String{
			return price>close?'#7F2200':(price==close?'#312122':'#3A6E30')
		}

		
	}
}
